package com.xyx.www;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

public class Test0809 {
	public static void main(String[] args) {
		// test02();获取Person Class对象
		// test03();获取Person Class类中的属性对象
		 test04();//获取获取Person的 Class类 中的方法
	}

	/**
	 * 使用反射获取一个类中的所有行为方法 方法的反射调用
	 */
	private static void test04() {
		// 创建一个学生对象的实例
		Person stu = new Person();
		// 设置stu对象姓名属性
		stu.setStuName("郭俊池");
		// 创建一个新的对象并设置属性
		Person stu1 = new Person();
		stu1.setStuName("王飞");
		// 通过被描述类的实例对象通过对象名.getClass();获取
		Class clazz1 = stu.getClass();
		Method[] method = clazz1.getDeclaredMethods();
		for (Method method2 : method) {
			// 使用反射获取访问控制修饰符
			System.out.print(Modifier.toString(method2.getModifiers()) + "  ");
			// 返回类型
			System.out.print(method2.getGenericReturnType().getTypeName() + "  ");
			// 方法名
			System.out.println(method2.getName() + "  ");
			//获得循环当前方法的形参列表
			Type[] ty=method2.getGenericParameterTypes();
			for (Type type : ty) {
				System.out.print("(");
				System.out.print(" "+type.getTypeName());
				System.out.print(")");
			}
		}
		/*System.out.println("======使用反射操作方法=======");
		try {
			// 通过方法名和方法的形参列表获取指定类型的方法对象【方法重载，所以不能通过方法名获取】
			Method mDoStuding = clazzStu.getDeclaredMethod("doStuding",String.class );
			// 使用Method对象的invoke方法，来执行该方法
			// invoke的第一个参数是被绑定的类的实例对象，第二个变长参数是执行该方法是所需要的实参列表
			// 注意：invoke的第二个参数的实参列表需要和获取该方法对象时给的形参列表保持一一对应；
			mDoStuding.invoke(stu0, "school");
			
			System.out.println("======================");
			stu0.doStuding("school");*/
		
	}

	/**
	 * 使用反射获取一个类中的所有属性信息
	 */
	private static void test03() {
		// 创建一个学生对象的实例
		Person stu = new Person();
		// 设置stu对象姓名属性
		stu.setStuName("郭俊池");
		// 创建一个新的对象并设置属性
		Person stu1 = new Person();
		stu1.setStuName("王飞");
		// 通过被描述类的实例对象通过对象名.getClass();获取
		Class clazz1 = stu.getClass();
		Field[] field = clazz1.getDeclaredFields();
		for (Field field2 : field) {
			System.out.print(Modifier.toString(field2.getModifiers()) + " ");
			System.out.print(field2.getGenericType().getTypeName() + " ");
			System.out.println(field2.getName());
		}
		System.out.println("------------------");

		try {
			// 获取指定属性的对象
			Field fieldStuName = clazz1.getDeclaredField("stuName");
			// 设置可以操作有属性的方法,可以操作私有属性
			fieldStuName.setAccessible(true);
			// 获取该类stuName属性对象在某个实例对象上的值
			String objName = (String) fieldStuName.get(stu);
			System.out.println("Person反射类中StuName对象在指定对象上的值：" + objName);
			System.out.println("Person反射类中StuName对象在指定对象上的值：" + fieldStuName.get(stu1));

			System.out.println("=====使用反射机制操作一个类的属性======");
			// 通过反射的属性对象，外部改变某一个实例对象的当前属性的值
			// 第一个参数是被操作类的实例对象stu，第二个参数被操作属性的值
			fieldStuName.set(stu1, "郑明");
			System.out.println("修改之后的值为 " + fieldStuName.get(stu1));

		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 获取一个类Class类实例对象创建被描述类的实例对象
	 */
	private static void test02() {
		// 创建Person类的Class类实例对象
		Class<Person> clazz1 = Person.class;
		// 通过newInstance方法获取Class类实例描述的类的实例对象
		try {
			Person per1 = clazz1.newInstance();
			per1.setStuName("郭俊池");
			System.out.println(per1.getStuName());
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 获取一个类或某个实例对象的Class类实例对象
	 */
	private static void test01() {
		// 通过class静态属性，类名.class获取
		Class<Person> clazz1 = Person.class;
		// 通过被描述类的实例对象通过对象名.getClass();获取
		Person per1 = new Person();
		Class<? extends Person> clazz2 = per1.getClass();
		// 使用Class类提供的静态方法forName获取,使用路径获取，抛出可能无法找到的检查性异常
		try {
			Class clazz3 = Class.forName("com.xyx.www.Person");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}
